HTTP API Reference¶
Verified status as of March 28, 2026. Runtime note: FastFN resolves dependencies and build steps per function: Python uses
requirements.txt, Node usespackage.json, PHP installs fromcomposer.jsonwhen present, and Rust handlers are built withcargo. Host runtimes/tools are required infastfn dev --native, whilefastfn devdepends on a running Docker daemon. Formal reference for public and internal endpoints.
Quick View¶
- Complexity: Reference
- Typical time: 15-30 minutes
- Use this when: you need exact endpoint contracts or status-code behavior
- Outcome: reproducible API calls for public routes and
/_fn/*operations
Conventions¶
- Local base URL:
http://127.0.0.1:8080 - Common error payload:
Public endpoints¶
FastFN serves functions at normal paths like /hello and /users/123.
These are the routes you see in:
GET /openapi.jsonGET /docs(Swagger UI)
GET|POST|PUT|PATCH|DELETE /<route>¶
Invokes the mapped function behind that route.
Mapped routes come from:
- file-based routes (Next.js-style),
fn.routes.json,- or explicit
fn.config.json -> invoke.routes.
GET example¶
POST example¶
curl -sS -X POST 'http://127.0.0.1:8080/risk-score?email=user@example.com' \
-H 'Content-Type: application/json' \
-d '{"source":"web"}'
Version pinning (optional)¶
FastFN supports side-by-side versions under the function directory (for example v2/).
GET|POST|PUT|PATCH|DELETE /<name>@<version>¶
Invokes a specific version by name.
Key rule (applies to all of the above):
- allowed methods come from
fn.config.json -> invoke.methods - if not allowed:
405+Allowheader
Custom routes via invoke.routes¶
By default, a function at functions/my-func/handler.py is reachable at /my-func. With invoke.routes you can expose it at one or more custom public URLs instead — useful for REST APIs, vanity paths, or mounting a function at a specific prefix.
routesis an array of URL paths. Each path becomes a public endpoint that invokes this function.- Wildcard routes are supported:
"/api/v1/*"matches/api/v1/anything/here. methodsrestricts which HTTP methods are allowed (default: all methods).- After discovery (startup or hot-reload), the gateway registers these routes automatically.
- If another function already maps the same route, the request is rejected unless
invoke.force-urlistrue.
Debug headers (opt-in)¶
When a function enables debug headers, responses can include:
X-Fn-RuntimeX-Fn-Runtime-RoutingX-Fn-Runtime-Socket-IndexX-Fn-Worker-Pool-Max-WorkersX-Fn-Worker-Pool-Max-Queue
This is useful when you want to confirm which runtime handled a request and whether traffic is rotating across multiple sockets.
Path operation configuration (FastFN equivalents)¶
FastFN does not use decorator-based path operation objects like FastAPI. Configuration is distributed between file routes and fn.config.json.
| FastAPI-style concept | FastFN equivalent | Notes |
|---|---|---|
| operation method/path | filename + folder path | source of truth is filesystem or fn.routes.json |
| allowed methods | invoke.methods |
enforced at gateway, returns 405 + Allow |
| summary | invoke.summary or handler hint @summary |
reflected in OpenAPI summary text |
| query/body examples | invoke.query, invoke.body, invoke.content_type |
used for OpenAPI request examples |
| operationId | generated automatically | format: <method>_<runtime>_<name>_<version> |
| tags | generated (functions / internal) |
no per-route custom tag mapping yet |
Non-1:1 note: if you need deep OpenAPI customization per operation, keep FastFN as runtime router and place extended schema transformations in your delivery pipeline.
Internal platform endpoints (/_fn/*)¶
Health and discovery¶
GET /_fn/healthPOST /_fn/reloadGET /_fn/catalogGET /_fn/packsGET /_fn/schedulesGET /_fn/jobsPOST /_fn/jobsGET /_fn/jobs/<id>DELETE /_fn/jobs/<id>GET /_fn/jobs/<id>/result
GET /_fn/health¶
Returns a runtime and route snapshot for the current process.
Example:
Simplified shape:
{
"python": {
"routing": "round_robin",
"health": { "up": true, "reason": "ok" },
"sockets": [
{ "index": 1, "uri": "unix:/tmp/fastfn/fn-python-1.sock", "up": true, "reason": "ok" },
{ "index": 2, "uri": "unix:/tmp/fastfn/fn-python-2.sock", "up": true, "reason": "ok" }
]
}
}
Use it to confirm:
- enabled runtimes
- runtime routing mode (
singleorround_robin) - per-socket health
- route conflict counts and function state summaries
CRUD and configuration¶
GET|POST|DELETE /_fn/functionGET|PUT /_fn/function-configGET|PUT /_fn/function-envPUT /_fn/function-code
Console operations¶
POST /_fn/invokePOST /_fn/loginPOST /_fn/logoutGET|POST|PUT|PATCH|DELETE /_fn/ui-state
/_fn/ui-state rules:
GETrequires Console API access.POST|PUT|PATCH|DELETErequire Console API access and write permission (FN_CONSOLE_WRITE_ENABLED=1or admin token).
/_fn/function-config PUT accepts top-level or nested route/method fields:
This is equivalent to the nested form:
{
"timeout_ms": 5000,
"invoke": {
"methods": ["GET", "POST"],
"routes": ["/alice/demo", "/alice/demo/{id}"]
}
}
When both top-level and invoke.* are provided, invoke.* takes precedence.
/_fn/function-env payload accepts:
- scalar values:
"KEY":"value" - secret objects:
"KEY":{"value":"secret","is_secret":true} nullto delete a key
GET /_fn/function can also return runtime dependency resolution metadata when the runtime emits it (today mainly Python/Node):
metadata.dependency_resolution.mode(manifestorinferred)metadata.dependency_resolution.manifest_generatedmetadata.dependency_resolution.infer_backendmetadata.dependency_resolution.inference_duration_msmetadata.dependency_resolution.inferred_importsmetadata.dependency_resolution.resolved_packagesmetadata.dependency_resolution.unresolved_importsmetadata.dependency_resolution.last_install_status/last_error
/_fn/invoke (full payload)¶
curl -sS 'http://127.0.0.1:8080/_fn/invoke' \
-X POST \
-H 'Content-Type: application/json' \
--data '{
"runtime":"node",
"name":"node-echo",
"version":null,
"method":"POST",
"query":{"name":"Node"},
"body":"{\"x\":1}",
"context":{"trace_id":"abc-123"}
}'
Fields:
runtimeoptional when name is not ambiguous- supported values:
python,node,php,rust namerequiredversionoptional (nullfor default)methodrequiredqueryoptional objectbodystring or JSON-serializable valuecontextoptional object forwarded toevent.context.user
OpenAPI and Swagger¶
GET /openapi.jsonGET /docs
OpenAPI is generated dynamically and reflects currently allowed methods per function/version.
Serialization and encoding edge cases¶
FastFN normalizes runtime output into HTTP, but serialization behavior still depends on the body type and response headers.
| Runtime return body | Header strategy | Client result |
|---|---|---|
| object/array | no explicit Content-Type |
JSON serialization with application/json |
| string | no explicit Content-Type |
plain text output |
| string JSON | application/json |
sent as text; clients parse JSON manually if needed |
| binary/base64 string | explicit content type + decoding at handler side | binary-safe delivery pattern |
Recommended deterministic pattern:
{
"status": 200,
"headers": { "Content-Type": "application/json; charset=utf-8" },
"body": { "ok": true }
}
Error table¶
| Code | Meaning | Typical cause |
|---|---|---|
404 |
function/version not found | unknown name/version |
405 |
method not allowed | calling POST on GET-only function |
409 |
route ambiguity | same function name across runtimes or same mapped route in multiple functions |
413 |
payload too large | body exceeds max_body_bytes |
429 |
concurrency limit reached | exceeds max_concurrency |
502 |
invalid runtime response | runtime contract violation |
503 |
runtime down | socket unavailable |
504 |
timeout | function exceeded timeout_ms |
500 |
internal error | gateway exception |
HTTP Lifecycle Diagram¶
flowchart LR
A["HTTP request"] --> B["Gateway"]
B --> C["Internal admin/public router"]
C --> D["Runtime invocation"]
D --> E["HTTP response"]
Contract¶
Defines expected request/response shape, configuration fields, and behavioral guarantees.
End-to-End Example¶
Use the examples in this page as canonical templates for implementation and testing.
Edge Cases¶
- Missing configuration fallbacks
- Route conflicts and precedence
- Runtime-specific nuances
See also¶
Extending OpenAPI: points and limits¶
Extension points:
- route metadata inferred from file routing + method files
- explicit examples in docs aligned with runtime behavior
- tags/operation grouping through naming conventions
Limits:
- OpenAPI should reflect real runtime behavior; avoid documenting statuses not returned by handlers.
- Advanced schema generation differs by runtime implementation details.
Validation command:
Validation¶
Run this smoke sequence:
curl -i -sS 'http://127.0.0.1:8080/_fn/health'
curl -sS 'http://127.0.0.1:8080/_fn/catalog' | jq '{mapped_routes, mapped_route_conflicts}'
curl -sS 'http://127.0.0.1:8080/openapi.json' | jq '.paths | keys | length'
Expected:
- health returns
200 - catalog returns mapped routes and deterministic conflict data
- OpenAPI paths count is non-zero for public projects
Troubleshooting¶
- If
/_fn/*returns401/403, check admin token and console-access flags. - If OpenAPI is empty, verify that at least one public route exists and is discoverable.
- If a route responds
405, verifyinvoke.methodsin function config. - If route calls return
503, verify runtime socket health in/_fn/health.
Next step¶
Continue with Run and test to validate this contract end-to-end in local/CI flows.
Related links¶
- Run and test
- Zero-config routing
- Platform runtime plumbing
- Function specification
- Runtime contract
- Built-in functions
- Architecture
- Get help